package com.inews.business.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.inews.base.exception.BusinessException;
import com.inews.base.mapper.BeanMapper;
import com.inews.base.persistence.DynamicSpecifications;
import com.inews.base.persistence.SearchFilter;
import com.inews.base.persistence.SearchFilter.Operator;
import com.inews.base.security.vo.BaseUserVo;
import com.inews.base.utils.ExtDataUtil;
import com.inews.base.utils.InewsUtils;
import com.inews.base.vo.ExtData;
import com.inews.business.constants.InewsBusinessConstants;
import com.inews.business.entity.TblSysResource;
import com.inews.business.entity.TblSysRole;
import com.inews.business.entity.TblSysRoleResource;
import com.inews.business.entity.TblSysUser;
import com.inews.business.repository.SysResourceDao;
import com.inews.business.repository.SysRoleDao;
import com.inews.business.repository.SysRoleResourceDao;
import com.inews.business.vo.RoleResourceTreeVo;
import com.inews.business.vo.SysRoleVo;

@Service
public class SysRoleServiceImpl implements SysRoleService, InewsBusinessConstants{
	
	@Autowired
	private SysRoleDao roleDao;
	@Autowired
	private SysResourceDao resourceDao;
	@Autowired
	private SysRoleResourceDao roleResourceDao;
	@Autowired
	private BaseService baseService;

	
	/**
	 * 分页查询系统角色.
	 *
	 * @param filterParams the filter params
	 * @param page the page
	 * @return the ext data
	 */
	@Transactional(readOnly=true)
	public ExtData<SysRoleVo> findSysRolePage(Map<String, Object> filterParams, Pageable page){
		Map<String, SearchFilter> filters = SearchFilter.parse(filterParams);
		filters.put("status", new SearchFilter("status", Operator.EQ, ROLE_STATUS_NORMAL));
		Page<TblSysRole> pagePoList = roleDao.findAll(DynamicSpecifications.bySearchFilter(filters.values(), TblSysRole.class), page);
		ExtData<SysRoleVo> extData = ExtDataUtil.genWithPagingList(pagePoList, SysRoleVo.class);
		return extData;
	}
	
	 
	/**
	 * 查询系统角色.
	 *
	 * @return the ext data
	 */
	@Transactional(readOnly=true)
	public ExtData<SysRoleVo> findSysRoleAll(){
		List<SysRoleVo> voList = new ArrayList<SysRoleVo>();
		Map<String, SearchFilter> filters = new HashMap<String, SearchFilter>();
		filters.put("status", new SearchFilter("status", Operator.EQ, ROLE_STATUS_NORMAL));
		List<TblSysRole> poList = roleDao.findAll(DynamicSpecifications.bySearchFilter(filters.values(), TblSysRole.class), new Sort(Direction.DESC, "roleId"));
		for (TblSysRole po : poList) {
			SysRoleVo vo = BeanMapper.map(po, SysRoleVo.class);
			voList.add(vo);
		}
		return ExtDataUtil.genWithData(voList);
	}
	
	
	
	/**
	 * 保存角色信息.
	 *
	 * @param vo the vo
	 * @param user the user
	 * @return the ext data
	 */
	@Transactional(readOnly=false)
	public ExtData<SysRoleVo> saveSysRole(SysRoleVo vo, BaseUserVo user){
		String currentTime = baseService.getCurrentTime();
		TblSysUser editUser = baseService.getEditUser(user);
		if(InewsUtils.isNotEmpty(roleDao.findByRoleName(vo.getRoleName()))){
			throw new BusinessException("该角色名已经存在，请重新输入");
		}
		TblSysRole po = BeanMapper.map(vo, TblSysRole.class);
		po.setStatus(ROLE_STATUS_NORMAL);
		po.setLastUpdDes(LAST_UPD_DES_ADD);
		po.setCreateTime(currentTime);
		po.setCreateUser(editUser);
		po.setLastUpdUser(editUser);
		po.setLastUpdTime(currentTime);
		roleDao.save(po);
		return ExtDataUtil.genWithSingleData(vo);
	}
	
	
	/**
	 * 更新角色信息.
	 *
	 * @param vo the vo
	 * @param user the user
	 * @return the ext data
	 */
	@Transactional(readOnly=false)
	public ExtData<SysRoleVo> updateSysRole(SysRoleVo vo, BaseUserVo user){
		String currentTime = baseService.getCurrentTime();
		TblSysUser editUser = baseService.getEditUser(user);
		TblSysRole po = roleDao.findOne(vo.getRoleId());
		if(!po.getRoleName().equals(vo.getRoleName())){
			if(InewsUtils.isNotEmpty(roleDao.findByRoleName(vo.getRoleName()))){
				throw new BusinessException("该角色名已经存在，请重新输入");
			}
		}
		po.setRoleName(vo.getRoleName());
		po.setLastUpdDes(LAST_UPD_DES_UPDATE);
		po.setLastUpdTime(currentTime);
		po.setLastUpdUser(editUser);
		roleDao.save(po);
		return ExtDataUtil.genWithSingleData(vo);
	}
	
	
	
	/**
	 * 删除角色信息.
	 *
	 * @param vo the vo
	 * @param user the user
	 * @return the ext data
	 */
	@Transactional(readOnly=false)
	public ExtData<SysRoleVo> deleteSysRole(SysRoleVo vo, BaseUserVo user){
		String currentTime = baseService.getCurrentTime();
		TblSysUser editUser = baseService.getEditUser(user);
		TblSysRole po = roleDao.findOne(vo.getRoleId());
		po.setStatus(ROLE_STATUS_DELETE);
		po.setLastUpdDes(LAST_UPD_DES_DELETE);
		po.setLastUpdTime(currentTime);
		po.setLastUpdUser(editUser);
		roleDao.save(po);
		return ExtDataUtil.genWithSingleData(vo);
	}
	
	
	
	/**
	 * 根据角色查找对应权限.
	 *
	 * @param vo the vo
	 * @return the ext data
	 */
	@Transactional(readOnly=true)
	public ExtData<RoleResourceTreeVo> findRoleResource(SysRoleVo vo){
		if(InewsUtils.isEmpty(vo.getRoleId())){
			return ExtDataUtil.genWithErrors("没有数据");
		}
		Map<String, TblSysRoleResource> roleResourceMap = new HashMap<String, TblSysRoleResource>();
		TblSysRole rolePo = roleDao.findOne(vo.getRoleId());
		Set<TblSysRoleResource> roleResources = rolePo.getRoleResources();
		for (TblSysRoleResource roleResource : roleResources) {
			roleResourceMap.put(roleResource.getResource().getResourceId(), roleResource);
		}
		//查询根资源
		TblSysResource rootResource = resourceDao.findOne(ROOT_RESOURCE);
		RoleResourceTreeVo treeVo = new RoleResourceTreeVo();
		treeVo = buildRoleResourceTree(treeVo, rootResource, roleResourceMap);
		return ExtDataUtil.genWithSingleData(treeVo);
	}



	/**
	 * 递归生成资源树.
	 *
	 * @param treeVo the tree vo
	 * @param rootResource the root resource
	 * @param roleResources 
	 * @return the role resource tree vo
	 */
	private RoleResourceTreeVo buildRoleResourceTree(RoleResourceTreeVo treeVo, TblSysResource resource, Map<String, TblSysRoleResource> roleResourceMap) {
		treeVo.setId(resource.getResourceId());
		treeVo.setText(resource.getResourceName());
		treeVo.setChecked(roleResourceMap.containsKey(resource.getResourceId()));
		if(InewsUtils.isEmpty(resource.getChildResources())){
			treeVo.setLeaf(true);
		}else{
			Set<TblSysResource> childResources = resource.getChildResources();
			for (TblSysResource childResource : childResources) {
				RoleResourceTreeVo childTreeVo = new RoleResourceTreeVo();
				childTreeVo = buildRoleResourceTree(childTreeVo, childResource, roleResourceMap);
				treeVo.getChildren().add(childTreeVo);
			}
		}
		return treeVo;
	}
	
	
	
	/**
	 * 分配权限.
	 *
	 * @param vo the vo
	 * @param roleResourceVos the role resource vos
	 * @param user the user
	 * @return the ext data
	 */
	@Transactional(readOnly=false)
	public ExtData<SysRoleVo> chooseResource(SysRoleVo vo, List<RoleResourceTreeVo> roleResourceVos, BaseUserVo user){
		String currentTime = baseService.getCurrentTime();
		TblSysUser editUser = baseService.getEditUser(user);
		Long roleId = vo.getRoleId();
		TblSysRole rolePo = roleDao.findOne(roleId);
		//删除原有的用户角色对应关系
		Set<TblSysRoleResource> roleResources = rolePo.getRoleResources();
		roleResourceDao.delete(roleResources);
		//添加用户角色信息
		for (RoleResourceTreeVo roleResourceVo : roleResourceVos) {
			TblSysResource resourcePo = resourceDao.findOne(roleResourceVo.getId());
			TblSysRoleResource roleResource = new TblSysRoleResource(rolePo, resourcePo);
			roleResourceDao.save(roleResource);
		}
		//更新最后修改用户和时间
		rolePo.setLastUpdTime(currentTime);
		rolePo.setLastUpdUser(editUser);
		rolePo.setLastUpdDes(InewsBusinessConstants.LAST_UPD_DES_UPDATE);
		roleDao.save(rolePo);
		return ExtDataUtil.genWithSingleData(vo);
	}
	
	
}
